package com.zmn.oms.api.listener;

import com.alibaba.fastjson.JSON;
import com.github.ltsopensource.core.domain.Job;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.manager.lts.interfaces.task.TaskManager;
import com.zmn.manager.mq.annotation.AliyunMQHandler;
import com.zmn.manager.mq.annotation.AliyunMQListener;
import com.zmn.oms.manager.utils.OmsMqTagConsts;
import com.zmn.oms.manager.utils.TaskConsts;
import com.zmn.oms.model.entity.chan.FacadeMessageEvent;
import com.zmn.oms.third.core.FacadeMessageEventHandlerFactory;
import com.zmn.oms.third.core.interfaces.FacadeMessageEventHandler;
import com.zmn.oms.zmn.business.interfaces.chan.FacadeMessageEventErrorBService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Objects;

/**
 * 类描述：工单变化状态推送
 *
 * @author liuying
 * @date 2019/06/11 11:44
 */
@Slf4j
@AliyunMQListener(topic = "${spring.mq.topic.oms}")
@Component
public class FacadeMessageEventListener {


    @Autowired
    private FacadeMessageEventErrorBService facadeMessageEventErrorBService;
    @Autowired
    private TaskManager taskManager;


    /**
     * 状态同步
     *
     * @param message
     */
    @AliyunMQHandler(tags = OmsMqTagConsts.CHAN_FACADE_MSG_EVENT_TAG)
    public void onFacadeMessageEvent(String message) {
        try {
            log.info("[FacadeMessageEvent] receive message:{}", message);
            FacadeMessageEvent facadeMessageEvent = JSON.parseObject(message, FacadeMessageEvent.class);

            // Event的年龄（被消费次数）
            int eventAge = facadeMessageEvent.getAge();

            // 处理消息
            if (!this.procEvent(facadeMessageEvent)) {
                facadeMessageEvent.setAge(++eventAge);
                this.onProcEventFail(facadeMessageEvent);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 处理消息
     * @param event
     * @return 是否处理成功
     */
    private boolean procEvent(FacadeMessageEvent event) {
        FacadeMessageEventHandler eventHandler = FacadeMessageEventHandlerFactory.getInstance(event);
        return eventHandler == null ? true : eventHandler.processEvent(event);
    }

    private void onProcEventFail(FacadeMessageEvent event) {
        boolean retriable = Objects.equals(GlobalConsts.YES, event.getRetriable());
        int age = event.getAge();

        if (retriable && age < FacadeMessageEvent.MAX_AGE) {
            // 处理失败且未达到最大处理次数，设置补偿处理
            // 10分钟后第一次重试，仍失败时，等半小时再重试第二次
            int minute = age > 1 ? (age-1)*30 : 10;
            this.addResendJob(event, minute);
            return;
        }

        String errorMsg = retriable ? "处理失败，已达到重试次数上限" : "处理失败";
        facadeMessageEventErrorBService.saveFacadeMessageEventError(event, errorMsg);
    }

    /**
     * 添加重发任务
     * @param event
     */
    private void addResendJob(FacadeMessageEvent event, int minute) {
        Job job = new Job();
        job.setTaskId(String.format("%s:%d:%d", TaskConsts.TASK_ID_RESEND_FACADE_MSG_EVENT_JOB,
                event.getClueId(), event.getAge()));
        job.setParam(TaskManager.SHARD_FIELD, TaskConsts.TASK_ID_RESEND_FACADE_MSG_EVENT_JOB);
        job.setParam("event", JSON.toJSONString(event));
        Date date = DateUtil.addMinute(DateUtil.getNow(), minute);

        taskManager.submitTask(job, -1, DateUtil.dateFormatToString(date, DateUtil.FORMAT_DEFAULT));
    }

}
